#include <lwip/tcp.h>
#include "mch.h"

static err_t  recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
  u16_t len = 0;
  struct pbuf *pit;

  if (p)
    len = p->tot_len;

  mch_printf("receive %d data from client\n", len);

  tcp_recved(pcb, len);

  /*write back as echo*/
  pit =  p;
  while (pit)
  {
      tcp_write(pcb, pit->payload, pit->len, 0);
      pit = pit->next; 
  }   

  tcp_close(pcb);
  err = ERR_OK;
  return err;

}


static err_t  accept_cb(void *arg, struct tcp_pcb *npcb, err_t err)
{

  mch_printf("Server:new connection from %s:%d\n",
      ipaddr_ntoa(&npcb->remote_ip),
      npcb->remote_port);  
 // tcp_accepted(npcb);
  tcp_setprio(npcb, TCP_PRIO_MIN);
  tcp_recv(npcb, recv_cb);
  /*Todo: asign this pcb to a cpu core*/

  err = ERR_OK;
  return err;
  
}


int server_init(struct ip_addr *ipaddr, u16_t port)
{
  struct tcp_pcb *pcb, *npcb;
  err_t err;

  pcb = tcp_new();
  if (!pcb)
  {
      mch_printf("tcp_new failed\n");
      return -1;
  }

  err = tcp_bind(pcb, ipaddr, port); 
  if (err != ERR_OK) 
  {
      mch_printf("tcp_bind failed\n");
      return -1;
  }

  npcb = tcp_listen(pcb);
  if (npcb == NULL)
  {
      mch_printf("tcp_listen failed\n");
      return -1;
  }

  tcp_accept(npcb, accept_cb);

  return 0;
}



